#include "stdafx.h"
#include "XmlLogging.h"

#import "msxml2.dll" 

#include <comdef.h>
#include <iostream>
#include <sstream>
#include <fstream>

static MSXML2::IXMLDOMDocumentPtr xmlDoc = NULL;
static MSXML2::IXMLDOMElementPtr  rootElement = NULL; 

void fsize(char *filename, long* size)
{
	long filesize = 0;
	std::fstream ifile(filename);
	if (!ifile) {
		*size = filesize;	
		return;
	}
	std::string str;
	char ch;
	while (ifile.get(ch)) {
		str += ch;
	}
	ifile.close();
	filesize = (long)str.length();
	*size = filesize;
}

void InstantiateDom()
{
  HRESULT hr;

  if (NULL != xmlDoc) {
    xmlDoc->Release();
    xmlDoc = NULL;
  }

  hr = xmlDoc.CreateInstance("msxml2.domdocument");
  SUCCEEDED(hr) ? 0 : throw hr; 
  xmlDoc->async = false;
  xmlDoc->resolveExternals = false;
  xmlDoc->AddRef();
}

XmlLogging::XmlLogging()
: CLogger()
{
  CoInitialize(NULL);
  InstantiateDom();
  
  long lFileSize = 0;
  char *pszXml = NULL;
  fsize(bstr_t(getLogName()) + ".xml", &lFileSize);
  if (lFileSize) {  
    std::string file(bstr_t(getLogName()) + ".xml");
    const char *name = file.c_str();
	  std::fstream ifile(name);
	  std::string str;
	  char ch;
	  while (ifile.get(ch)) {
		  str += ch;
	  }
    ifile.close();

    pszXml = new char[strlen(str.c_str()) +1];
    memset(pszXml, 0, strlen(str.c_str()) +1);
    strncpy(pszXml, str.c_str(), strlen(str.c_str()));
  } else {
    const char szRoot[] = "<Entries></Entries>";

    pszXml = new char[strlen(szRoot) +1];
    memset(pszXml, 0, strlen(szRoot) +1);
    strncpy(pszXml, szRoot, strlen(szRoot));
  }
  
  xmlDoc->loadXML(pszXml); 

  delete[] pszXml;

  rootElement = xmlDoc->documentElement;
  (NULL != rootElement) ? 0 : throw "parse error"; 
  rootElement->AddRef();  
}

XmlLogging::~XmlLogging()
{
  if (NULL == rootElement) {
    rootElement->Release();
    rootElement = NULL;
  }
  if (NULL == xmlDoc) {
    xmlDoc->Release();
    xmlDoc = NULL;
  }
}

void XmlLogging::write(CEntry * entry)
{
  MSXML2::IXMLDOMElementPtr nodeEntry; 
  nodeEntry = xmlDoc->createElement("Entry");

  MSXML2::IXMLDOMNodePtr nodeAttr;
  nodeAttr = xmlDoc->createNode(MSXML2::NODE_ATTRIBUTE,  "Guid", "");
  nodeAttr->put_text(bstr_t(entry->getGuid()));  
  nodeEntry->attributes->setNamedItem(nodeAttr);

  MSXML2::IXMLDOMElementPtr nodeTs; 
  nodeTs = xmlDoc->createElement("Timestamp");
  nodeTs->put_text(bstr_t(entry->getTimestamp()));
  nodeEntry->appendChild(nodeTs);

  MSXML2::IXMLDOMElementPtr nodeId; 
  nodeId = xmlDoc->createElement("Id");
  nodeId->put_text(bstr_t(entry->getId()));
  nodeEntry->appendChild(nodeId);
  
  MSXML2::IXMLDOMElementPtr nodeSev; 
  nodeSev = xmlDoc->createElement("Severity");
  nodeSev->put_text(bstr_t(entry->getSeverity()));
  nodeEntry->appendChild(nodeSev);

  MSXML2::IXMLDOMElementPtr nodeDescr; 
  nodeDescr = xmlDoc->createElement("Description");
  nodeDescr->put_text(bstr_t(entry->getDescription()));
  nodeEntry->appendChild(nodeDescr); 
   
  MSXML2::IXMLDOMCDATASectionPtr stack;
  stack = xmlDoc->createCDATASection("StackTrace");
  stack->put_text(bstr_t(entry->getStackTrace()));  
  nodeEntry->appendChild(stack);
  
  rootElement->appendChild(nodeEntry);
  xmlDoc->save(bstr_t(getLogName()) + ".xml");
}
